<?php

namespace App\Service\Article;

use App\Http\Middleware\OpenShop\FeishuWebAuth;
use App\Http\Middleware\OpenShop\MerchantAppAuth;
use App\Http\Resources\Article\ApiArticleListResource;
use App\Http\Resources\Article\ApiArticleVideoListResource;
use App\Http\Resources\Article\ArticleDetailResource;
use App\Http\Resources\Article\ArticleListResource;
use App\Http\Resources\Article\RecommendListResource;
use App\Http\Resources\Article\Tab\CategortyListResource;
use App\Http\Resources\Article\Tab\HotListResource;
use App\Http\Resources\Article\UserOperateListResource;
use App\Jobs\Article\ArticleOperate;
use App\Models\Article\ArticleCategoryMappingsModel;
use App\Models\Article\ArticleCategoryModel;
use App\Models\Article\ArticleModel;
use App\Models\Article\ArticleRecommendModel;
use App\Models\Article\ArticleStatisticsDayModel;
use App\Models\Article\ArticleStatisticsLogsModel;
use App\Models\Article\ArticleUserRelationModel;
use App\Models\Common\FileTranscodingJobModel;
use App\Service\BaseService;
use App\Service\Common\UploadTranscoding;
use Exception;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Sunra\PhpSimple\HtmlDomParser;

class ArticleService extends BaseService
{
    /**
     * 添加 文章/视频
     *
     * @param object $params
     * @throws Exception
     */
    public static function add(object $params)
    {

        try {
            $insert = [];
            switch ($params->publishType) {
                case ArticleModel::PUBLISH_TYPE_TIMING:
                    $insert = array_merge($insert, [
                        "effectiveTime" => strtotime($params->effectiveTime),
                        "status"        => ArticleModel::STATUS_ON,
                    ]);
                    break;
                case ArticleModel::PUBLISH_TYPE_DRAFT:
                    $insert = array_merge($insert, [
                        "effectiveTime" => 0,
                        "status"        => ArticleModel::STATUS_OFF
                    ]);
                    break;
                case ArticleModel::PUBLISH_TYPE_NOW:
                    $insert = array_merge($insert, [
                        "effectiveTime" => time(),
                        "status"        => ArticleModel::STATUS_ON,
                    ]);
                    break;
            }

            $articleId = ArticleModel::query()->insertGetId(
                collect(array_merge((array)$params, [
                    "previewUrl"   => json_encode($params->previewUrl, JSON_UNESCAPED_UNICODE),
                    "createdAt"    => time(),
                    "createdByUid" => request()->user()->id
                ], $insert))->toArray()
            );

            //转码
            self::handleArticleTranscoding($params, $articleId);

        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @param $articleId
     */
    public static function handleArticleTranscoding(object $params, $articleId)
    {
        try {
            switch ($params->type) {
                case ArticleModel::TYPE_VIDEO:
                    $transcodingVideoDetail = self::transcodingVideo(
                        $articleId,
                        ArticleModel::class,
                        [$params->content],
                        ["article-video-264"]
                    );
                    break;
                case ArticleModel::TYPE_ARTICLE:
                    $html                   = str_get_html($params->content);
                    $transcodingVideoDetail = self::transcodingVideo(
                        $articleId,
                        ArticleModel::class,
                        collect($html->find("source"))->pluck("src")->toArray(),
                        ["article-video-264"]
                    );
                    break;
                default:
                    throw new Exception("类型传入有误");
            }

            //写入转码详情
            ArticleModel::query()->where("id", $articleId)->update([
                "transcodingVideoDetail" => json_encode($transcodingVideoDetail, JSON_UNESCAPED_UNICODE)
            ]);
        } catch (Exception $exception) {
            logException("添加转码任务失败", $exception, ["id" => $articleId], true, true);
        }
    }

    /**
     * @param int $modelId
     * @param string $modelName
     * @param array $filePaths
     * @param array $keys
     * @return array
     */
    public static function transcodingVideo(int $modelId, string $modelName, array $filePaths, array $keys): array
    {
        $keysGroup  = collect($keys);
        $fileJobMap = $fileJobInsert = [];
        collect($filePaths)->map(function (string $filePath) use (
            $keysGroup,
            $modelId,
            $modelName,
            &$fileJobMap,
            &$fileJobInsert
        ) {
            array_push($fileJobMap, [
                "original"               => $filePath,
                "transcodingVideoDetail" => $keysGroup->map(function (string $key) use (
                    $modelId,
                    $filePath,
                    $modelName,
                    &$fileJobMap,
                    &$fileJobInsert
                ) {
                    $filePathKey     = trim(parse_url($filePath)["path"], "/");
                    $filePathEncoded = vsprintf(
                        "%s_%s_encoded.mp4", [
                            explode(".", $filePathKey)[0],
                            $key
                        ]
                    );
                    $jobId           = UploadTranscoding::asyncFileTranscoding(
                        $filePathKey,
                        config("file-transcoding.{$key}"),
                        "",
                        $filePathEncoded
                    );
                    array_push($fileJobInsert, [
                        "jobId"           => $jobId,
                        "model"           => $modelName,
                        "filePath"        => $filePathKey,
                        "updatedField"    => "content",
                        "updatedModelId"  => $modelId,
                        "filePathEncoded" => $filePathEncoded,
                        "status"          => FileTranscodingJobModel::STATUS_WAIT
                    ]);
                    return [
                        "jobId" => $jobId,
                        "key"   => $key
                    ];
                })->values()->toArray()
            ]);
        });

        FileTranscodingJobModel::query()->insert($fileJobInsert);
        return $fileJobMap;
    }

    /**
     * 编辑 文章/视频
     *
     * @param object $params
     * @throws Exception
     */
    public static function update(object $params)
    {
        try {
            $update = [];
            $info   = ArticleModel::query()->where("id", $params->id)->first();
            if (property_exists($params, "publishType")) {
                switch ($params->publishType) {
                    case ArticleModel::PUBLISH_TYPE_TIMING:
                        $update = array_merge($update, [
                            "effectiveTime" => strtotime($params->effectiveTime),
                            "status"        => ArticleModel::STATUS_ON,
                        ]);

                        // 从草稿状态发布时修改创建时间为当前时间
                        if ($info && $info->publishType == ArticleModel::PUBLISH_TYPE_DRAFT) {
                            $update = array_merge($update, ["createdAt" => time()]);
                        }
                        break;
                    case ArticleModel::PUBLISH_TYPE_DRAFT:
                        $update = array_merge($update, [
                            "status" => ArticleModel::STATUS_OFF,
                        ]);
                        break;
                    case ArticleModel::PUBLISH_TYPE_NOW:
                        $update = array_merge($update, [
                            "status"        => ArticleModel::STATUS_ON,
                            "effectiveTime" => time()
                        ]);

                        // 从草稿状态发布时修改创建时间为当前时间
                        if ($info && $info->publishType == ArticleModel::PUBLISH_TYPE_DRAFT) {
                            $update = array_merge($update, ["createdAt" => time()]);
                        }
                        break;
                }
            }


            ArticleModel::query()->where("id", $params->id)->update(
                collect(array_merge((array)$params, [
                    "previewUrl"   => json_encode($params->previewUrl, JSON_UNESCAPED_UNICODE),
                    "updatedAt"    => time(),
                    "updatedByUid" => request()->user()->id
                ], $update))->except(["id", "saveOnly"])->toArray()
            );

            //转码
            self::handleArticleTranscoding($params, $params->id);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 查看 文章/视频 详情
     *
     * @param int $id
     * @return array|void
     * @throws Exception
     */
    public static function detail(int $id)
    {
        try {
            $action       = request()->route()->getAction();
            $articleModel = ArticleModel::query()->with([
                "createUserRel",
                "articleCategoryMappingsRel.articleCategoryRel"
            ])->where("id", $id)->first();

            $middleware = attributeGet($action, "middleware", []);
            if (!in_array(FeishuWebAuth::class, $middleware)) {

                $uid = 0;
                if (in_array(MerchantAppAuth::class, $middleware)) {
                    $uid                     = request()->user()->id;
                    $articleModel->isCollect = ArticleUserRelationModel::checkIfCollect($uid, $id);
                    $articleModel->isSupport = ArticleUserRelationModel::checkIfSupport($uid, $id);
                }


                // 异步处理
                dispatch(
                    (new ArticleOperate(
                        [
                            'type'      => ArticleStatisticsLogsModel::TYPE_READ,
                            'articleId' => $id,
                            'userId'    => $uid,
                        ]
                    ))
                )->onQueue(ArticleOperate::QUEUE_NAME);
                // 增加文章阅读数
//                ArticleOperateService::operate(ArticleStatisticsLogsModel::TYPE_READ, $id, $uid);
            }

            // 小程序获取 url link
            $urlLink = \EasyWeChat::miniProgram('callingCards')->url_link->generate([
                'path' => 'pages/official-website/official-website'
            ]);

            return [
                "detail"             => ArticleDetailResource::collection([$articleModel])->getIterator()->current(),
                'miniProgramUrlLink' => $urlLink ? ($urlLink['url_link'] ?? '') : '',
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 删除 文章/视频
     *
     * @param int $id
     * @return void
     * @throws Exception
     */
    public static function del(int $id)
    {
        try {
            ArticleModel::query()->where("id", $id)->update([
                "isDeleted"    => ArticleModel::DELETE_YES,
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id
            ]);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }


    /**
     * 列表
     *
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function articleList(object $params)
    {
        try {
            $paginate = ArticleModel::query()
                                    ->with(["createUserRel"])
                                    ->when(checkFieldLen($params, "categoryId"), function ($query) use ($params) {
                                        $query->whereNotIn("id",
                                            function ($query) use ($params) {
                                                $query->select("articleId")->from(
                                                    (new ArticleCategoryMappingsModel())->getTable()
                                                )->where("isDeleted", 0);
                                            });
                                    })
                                    ->when(
                                        attributeGet($params, "isDrafts", null),
                                        function ($query) use ($params) {
                                            $query->where("publishType", ArticleModel::PUBLISH_TYPE_DRAFT);
                                        },
                                        function ($query) use ($params) {
                                            $query->where("publishType", ">", ArticleModel::PUBLISH_TYPE_DRAFT);
                                        })
                                    ->when(
                                        checkFieldLen($params, "title"),
                                        function ($query) use ($params) {
                                            $query->where("title", "like", "%{$params->title}%");
                                        })
                                    ->when(
                                        attributeGet($params, "type", null),
                                        function ($query) use ($params) {
                                            $query->where("type", $params->type);
                                        })
                                    ->when(
                                        checkFieldLen($params, "status"),
                                        function ($query) use ($params) {
                                            $query->where("status", $params->status);
                                        })
                                    ->when(
                                        checkFieldLen($params, "publishStatus"),
                                        function ($query) use ($params) {
                                            switch ($params->publishStatus) {
                                                case ArticleModel::PUBLISH_SELECTION_YES:
                                                    $query->where("effectiveTime", "<=", time());
                                                    break;
                                                case ArticleModel::PUBLISH_SELECTION_NO:
                                                    $query->where("effectiveTime", ">=", time());
                                                    break;
                                            }
                                        })
                                    ->when(
                                        attributeGet($params, "createStartTime", null),
                                        function ($query) use ($params) {
                                            $query->where("createdAt", ">=", strtotime($params->createStartTime));
                                        })
                                    ->when(
                                        attributeGet($params, "createEndTime", null),
                                        function ($query) use ($params) {
                                            $query->where("createdAt", "<",
                                                strtotime("+1 day", strtotime($params->createEndTime)));
                                        })
                                    ->when(
                                        attributeGet($params, "effectiveStartTime", null),
                                        function ($query) use ($params) {
                                            $query->where("effectiveTime", ">=",
                                                strtotime($params->effectiveStartTime));
                                        })
                                    ->when(
                                        attributeGet($params, "effectiveEndTime", null),
                                        function ($query) use ($params) {
                                            $query->where("effectiveTime", "<",
                                                strtotime("+1 day", strtotime($params->effectiveEndTime)));
                                        })
                                    ->when(
                                        attributeGet($params, "createdByUid", null),
                                        function ($query) use ($params) {
                                            $query->where("createdByUid", $params->createdByUid);
                                        })
                                    ->when(
                                        attributeGet($params, "sortField", null),
                                        function ($query) use ($params) {
                                            $sort = attributeGet(
                                                $params,
                                                "sortOrder",
                                                "descend"
                                            ) == "descend" ? "desc" : "asc";
                                            $query->orderBy($params->sortField, $sort);
                                        },
                                        function ($query) {
                                            $query->orderByDesc("putTop")
                                                  ->orderBy("sort")
                                                  ->orderByDesc("effectiveTime")
                                                  ->orderBy("id", "desc");
//                                            $query->orderBy("putTop", "desc")
//                                                  ->orderBy("sort", "desc")
//                                                  ->orderBy("createdAt", "desc");
                                        }
                                    )
                                    ->when(!empty($params->statisticalEndAt) && !empty($params->statisticalStartAt),
                                        function ($query) use ($params) {
                                            $ids = ArticleStatisticsDayModel::query()
                                                                            ->whereBetween('dateAt', [
                                                                                strtotime($params->statisticalStartAt . ' 00:00:00'),
                                                                                strtotime($params->statisticalEndAt . ' 23:59:59')
                                                                            ])
                                                                            ->where('articleId', '!=', 0)
                                                                            ->limit(30)
                                                                            ->where('source',
                                                                                ArticleStatisticsDayModel::TYPE_READ)
                                                                            ->select(DB::raw('sum(netIncNum) as netIncNum,articleId'))
                                                                            ->groupBy('articleId')
                                                                            ->orderByDesc('netIncNum')
                                                                            ->get()
                                                                            ->pluck('articleId')
                                                                            ->unique()
                                                                            ->values();

                                            $query->whereIn('id', $ids)
                                                  ->reorder()
                                                  ->orderByRaw(DB::raw("FIELD(id, " . implode(',',
                                                          $ids->toArray()) . ")"))
                                                  ->limit(10);
                                        })
                                    ->paginate($params->pageSize, ['*'], 'pageNum', $params->pageNum);

            return [
                "list"       => ArticleListResource::collection($paginate->items()),
                "count"      => $paginate->total(),
                "pageNum"    => $params->pageNum,
                "pageSize"   => $params->pageSize,
                "draftCount" => ArticleModel::query()
                                            ->where("publishType", ArticleModel::PUBLISH_TYPE_DRAFT)
                                            ->count()
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 商家端首页信息流
     *
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function indexList(object $params)
    {
        try {
            $paginate = ArticleModel::query()
                                    ->with([
                                        "articleUserRelationRel"     => function ($query) {
                                            $query->where("createdByUid", request()->user()->id)
                                                  ->whereIn("type", [
                                                      ArticleUserRelationModel::TYPE_LIKE,
                                                      ArticleUserRelationModel::TYPE_COLLECT
                                                  ])
                                                  ->where("status", ArticleUserRelationModel::STATUS_SUCCESS);
                                        },
                                        "articleCategoryMappingsRel" => function ($query) {
                                            $query->with([
                                                "articleCategoryRel" => function ($query) {
                                                    $query->withCount("articleCategoryMappingsRel as articleCategoryMappingsRelCount")
                                                          ->with([
                                                              "articleCategoryMappingsRel" => function ($query) {
                                                                  $query->whereHas(
                                                                      "articleRel",
                                                                      function ($query) {
                                                                          $query->where("status",
                                                                              ArticleModel::STATUS_ON)
                                                                                ->whereIn("publishType",
                                                                                    [
                                                                                        ArticleModel::PUBLISH_TYPE_TIMING,
                                                                                        ArticleModel::PUBLISH_TYPE_NOW
                                                                                    ])
                                                                                ->where("effectiveTime", "<=", time())
                                                                                ->where("isDeleted", 0);
                                                                      }
                                                                  );
                                                              }
                                                          ]);
                                                }
                                            ]);
                                        }
                                    ])
                                    ->where("sort", '<', '9999') // 9999 以外的排序不展示
                                    ->where("status", ArticleModel::STATUS_ON)
                                    ->whereIn("publishType",
                                        [ArticleModel::PUBLISH_TYPE_TIMING, ArticleModel::PUBLISH_TYPE_NOW])
                                    ->where("effectiveTime", "<=", time())
                                    ->orderByDesc("putTop")
                                    ->orderBy("sort")
                                    ->orderByDesc("effectiveTime")
                                    ->orderBy("id", "desc")
                                    ->paginate($params->pageSize, ['*'], 'pageNum', $params->pageNum);


            return [
                "list"     => ApiArticleListResource::collection($paginate->items()),
                "count"    => $paginate->total(),
                "pageNum"  => $params->pageNum,
                "pageSize" => $params->pageSize
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }


    /**
     * 操作列表
     *
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function operateList(object $params)
    {
        try {
            $paginate = ArticleUserRelationModel::query()
                                                ->where("status", ArticleUserRelationModel::STATUS_SUCCESS)
                                                ->where("type", $params->type)
                                                ->where("createdByUid", request()->user()->id)
                                                ->with(["articleRel"])
                                                ->whereHas("articleRel", function ($query) use ($params) {
                                                    if (checkFieldLen($params, "title")) {
                                                        $query->where("title", "like", "%{$params->title}%");
                                                    }
                                                })
                                                ->orderBy("id", "desc")
                                                ->paginate($params->pageSize, ['*'], 'pageNum', $params->pageNum);

            return [
                "list"     => UserOperateListResource::collection($paginate->items()),
                "count"    => $paginate->total(),
                "pageNum"  => $params->pageNum,
                "pageSize" => $params->pageSize
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 上下架 内容
     *
     * @param object $params
     * @throws Exception
     */
    public static function status(object $params)
    {
        try {
            ArticleModel::query()->where("id", $params->id)->update([
                "status"       => $params->status,
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id
            ]);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 列表页修改排序接口
     *
     * @param object $params
     * @throws Exception
     */
    public static function sort(object $params)
    {
        try {
            ArticleModel::query()->where("id", $params->id)->update([
                "sort"         => $params->sort,
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id
            ]);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 置顶
     *
     * @param object $params
     * @throws Exception
     */
    public static function putTop(object $params)
    {
        try {
            ArticleModel::query()->where("id", $params->id)->update([
                "putTop"       => $params->putTop,
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id
            ]);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 替换转码视频
     *
     * @param string $content
     * @param string|null $transcodingVideoDetail
     * @return array|string|string[]
     */
    public static function replaceTranscodingContent(
        string $content,
        ?string $transcodingVideoDetail
    ) {
        if (!property_exists(request(), "fileTranscodingKey")) {
            self::getFileTranscodingKey();
        }

        if (!empty($transcodingVideoDetail) && isJson($transcodingVideoDetail)) {
            collect(jsonToArr($transcodingVideoDetail))
                ->each(function ($transcodingDetail) use (&$content) {
                    if (request()->fileTranscodingKey) {
                        $appVersion = request()->header("version", "");
                        $suffix     = version_compare($appVersion, "3.9.2", ">") ? "?x-oss-traffic-limit=16384000" : "";

                        $replaceDetail = collect($transcodingDetail["transcodingVideoDetail"] ?? [])
                            ->where("key", request()->fileTranscodingKey)->first();
                        if (!empty($replaceDetail["url"])) {
                            $replaceUrl = $replaceDetail["url"] . $suffix;
                        } else {
                            $replaceUrl = $transcodingDetail["original"] . $suffix;
                        }

                        $content = str_replace(
                            $transcodingDetail["original"],
                            $replaceUrl,
                            $content
                        );
                    }
                });
        }
        return $content;
    }

    /**
     * 获取转码key
     */
    public static function getFileTranscodingKey()
    {
        $requestFrom = requestFromFunc();
        switch ($requestFrom) {
//            case MerchantAppAuth::class:
//                request()->fileTranscodingKey = "article-video-265";
//                break;
            case FeishuWebAuth::class:
                request()->fileTranscodingKey = "";
                break;
            default:
                request()->fileTranscodingKey = "article-video-264";
        }
    }

    /**
     * @param object $params
     * @return array
     * @throws Exception
     */
    public static function videoList(object $params): array
    {
        try {
            $categoryId = attributeGet($params, "categoryId", 0);

            $RecommendVideo = null;
            if (empty($categoryId) && attributeGet($params, "pageNum", null) == 1) {
                $RecommendVideo = ArticleRecommendModel::query()
                                                       ->where("contentType",
                                                           ArticleRecommendModel::CONTENT_TYPE_ARTICLE)
                                                       ->where(function ($query) {
                                                           $query->where("effectiveType",
                                                               ArticleRecommendModel::EFFECTIVE_TYPE_ALWAYS)
                                                                 ->orWhere(function ($query) {
                                                                     $query->where("effectiveType",
                                                                         ArticleRecommendModel::EFFECTIVE_TYPE_LIMIT)
                                                                           ->where('startAt', '<', time())
                                                                           ->where('endAt', '>', time());

                                                                 });
                                                       })
                                                       ->with([
                                                           "articleRel" => function ($query) {
                                                               $query->with([
                                                                   "articleUserRelationRel",
                                                                   "articleCategoryMappingsRel.articleCategoryRel"
                                                               ]);
                                                           }
                                                       ])->orderBy("type")
                                                       ->orderBy('sort')
                                                       ->orderByDesc('id')
                                                       ->get()->pluck("articleRel");
            }
            $categoryDetail = null;
            $paginate       = ArticleModel::query()
                                          ->with([
                                              "articleUserRelationRel" => function ($query) {
                                                  $query->where("createdByUid", request()->user()->id)
                                                        ->whereIn("type", [
                                                            ArticleUserRelationModel::TYPE_LIKE,
                                                            ArticleUserRelationModel::TYPE_COLLECT
                                                        ])
                                                        ->where("status", ArticleUserRelationModel::STATUS_SUCCESS);
                                              }
                                          ])
                                          ->where("status", ArticleModel::STATUS_ON)
                                          ->whereIn("publishType",
                                              [ArticleModel::PUBLISH_TYPE_TIMING, ArticleModel::PUBLISH_TYPE_NOW])
                                          ->where("effectiveTime", "<=", time())
                                          ->when(
                                              empty($categoryId),
                                              function ($query) use ($params) {
                                                  return $query->with([
                                                      "articleCategoryMappingsRel" => function ($query) {
                                                          $query->with([
                                                              "articleCategoryRel" => function ($query) {
                                                                  $query->where("isDeleted", 0);
                                                              }
                                                          ])->where("isDeleted", 0);
                                                      }
                                                  ])
//                                                               ->where("id", ">=", $params->articleId)
//                                                               ->where("type", ArticleModel::TYPE_VIDEO)
                                                               ->orderByDesc("putTop")
                                                               ->orderBy("sort")
                                                               ->orderByDesc("effectiveTime")
                                                               ->orderBy("id", "desc")
                                                               ->paginate($params->pageSize, ['*'], 'pageNum',
                                                                   $params->pageNum);
                                              },
                                              function ($query) use (&$params, &$categoryDetail, $categoryId) {
                                                  $params->pageSize = 1000;
                                                  $params->pageNum  = 1;
                                                  $categoryDetail   = ArticleCategoryModel::query()
                                                                                          ->where("id", $categoryId)
                                                                                          ->where("isDeleted", 0)
                                                                                          ->first();
                                                  return $query->join(
                                                      (new ArticleCategoryMappingsModel())->getTable() . " as ac_m",
                                                      "ac_m.articleId",
                                                      "=",
                                                      "article.id"
                                                  )->where("ac_m.categoryId", $categoryId)
                                                               ->where("ac_m.isDeleted", 0)
                                                               ->where("article.type", ArticleModel::TYPE_VIDEO)
                                                               ->where("article.isDeleted", 0)
                                                               ->orderBy("ac_m.sort")
                                                               ->orderBy("ac_m.updatedAt", "desc")
                                                               ->paginate(
                                                                   $params->pageSize,
                                                                   ['article.*'],
                                                                   'pageNum',
                                                                   $params->pageNum
                                                               );
                                              }
                                          );


            return [
                "category" => $categoryDetail ? $categoryDetail->only([
                    "id",
                    "description",
                    "name",
                    "cover",
                    "showNum",
                    "readNum",
                    "forwardNum",
                    "collectNum",
                    "supportNum"
                ]) : null,
                "list"     => ApiArticleVideoListResource::collection(collect($paginate->items())->when(
                    $RecommendVideo && $RecommendVideo->isNotEmpty(),
                    function ($query) use ($RecommendVideo) {
                        return $query->merge($RecommendVideo);
                    })),
                "count"    => $RecommendVideo ? $RecommendVideo->count() + $paginate->total() : $paginate->total(),
                "pageNum"  => $params->pageNum,
                "pageSize" => $params->pageSize
            ];

        } catch (Exception $exception) {
            throw $exception;
//            handleKfException($exception);
        }
    }

    /**
     * 热榜置顶
     *
     * @param object $params
     * @throws Exception
     */
    public static function putHotTop(object $params)
    {
        if ($params->putHotTop == ArticleModel::PUT_TOP_YES) {
            ArticleModel::query()->where("putHotTop", ArticleModel::PUT_TOP_YES)->update([
                "putHotTop"    => ArticleModel::PUT_TOP_NO,
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id
            ]);
        }

        ArticleModel::query()->where("id", $params->id)->update([
            "putHotTop"    => $params->putHotTop,
            "updatedAt"    => time(),
            "updatedByUid" => request()->user()->id
        ]);
    }

    /**
     * 首页文章tab
     *
     * @return array
     */
    public static function tab(): array
    {
        return [
            "list" => array_merge(
                [
                    [
                        "type" => ArticleModel::INDEX_TAB_TYPE_1,
                        "text" => ArticleModel::INDEX_TAB_TYPE_TEXT[ArticleModel::INDEX_TAB_TYPE_1],
                        "id"   => 0,
                    ],
                    [
                        "type" => ArticleModel::INDEX_TAB_TYPE_2,
                        "text" => ArticleModel::INDEX_TAB_TYPE_TEXT[ArticleModel::INDEX_TAB_TYPE_2],
                        "id"   => 0,
                    ]
                ],
                ArticleCategoryModel::query()
                                    ->where("putTop", ArticleCategoryModel::PUT_TOP_YES)
                                    ->limit(6)
                                    ->orderBy("sort")
                                    ->get()
                                    ->map(function (ArticleCategoryModel $articleCategoryModel) {
                                        return [
                                            "type" => ArticleModel::INDEX_TAB_TYPE_0,
                                            "id"   => $articleCategoryModel->id,
                                            "text" => $articleCategoryModel->name
                                        ];
                                    })->values()->toArray(),
                [
                    [
                        "type" => ArticleModel::INDEX_TAB_TYPE_3,
                        "text" => ArticleModel::INDEX_TAB_TYPE_TEXT[ArticleModel::INDEX_TAB_TYPE_3],
                        "id"   => 0,
                    ]
                ]
            )
        ];
    }

    /**
     * 获取tab数据集
     *
     * @param object $params
     * @return array
     */
    public static function tabContent(object $params): array
    {
        $function = "contentType_{$params->type}";
        return [
            "tabDesc" => ArticleModel::INDEX_TAB_TYPE_TEXT[$params->type],
            "data"    => self::$function($params)
        ];
    }

    /**
     * tab_0 内容展示
     *
     * @param object $params
     * @return array
     */
    protected static function contentType_0(object $params): array
    {
        $pagination = ArticleCategoryMappingsModel::query()
                                                  ->whereHas("articleRel", function ($query) {
                                                      $query->where("status", ArticleModel::STATUS_ON);
                                                  })
                                                  ->with([
                                                      "articleRel" => function ($query) {
                                                          $query->with([
                                                              "articleUserRelationRel" => function ($query) {
                                                                  $query->where("createdByUid", request()->user()->id)
                                                                        ->whereIn("type", [
                                                                            ArticleUserRelationModel::TYPE_LIKE,
                                                                            ArticleUserRelationModel::TYPE_COLLECT
                                                                        ])
                                                                        ->where("status",
                                                                            ArticleUserRelationModel::STATUS_SUCCESS);
                                                              }
                                                          ]);
                                                      }
                                                  ])
                                                  ->where("categoryId", $params->id)
                                                  ->orderBy("sort")
                                                  ->paginate(
                                                      $params->pageSize,
                                                      ["*"],
                                                      'pageNum',
                                                      $params->pageNum
                                                  );

        return [
            "total"    => $pagination->total(),
            "pageSize" => $params->pageSize,
            "list"     => ApiArticleListResource::collection(collect($pagination->items())->pluck("articleRel")),
            "pageNum"  => $params->pageNum,
        ];
    }

    /**
     * 获取最新tab数据集
     *
     * @param object $params
     * @return array
     */
    protected static function contentType_1(object $params): array
    {
        $list = ArticleRecommendModel::query()->with(['articleRel'])
                                     ->where("type", ArticleRecommendModel::TYPE_NEW)
                                     ->where('isActivate', ArticleRecommendModel::ACTIVATE_ON)
                                     ->where(function ($query) {
                                         $query->where("effectiveType",
                                             ArticleRecommendModel::EFFECTIVE_TYPE_ALWAYS)
                                               ->orWhere(function ($query) {
                                                   $query->where("effectiveType",
                                                       ArticleRecommendModel::EFFECTIVE_TYPE_LIMIT)
                                                         ->where('startAt', '<', time())
                                                         ->where('endAt', '>', time());
                                               });
                                     })
                                     ->orderBy('sort')
                                     ->orderByDesc('id')
                                     ->get();

        return ["list" => RecommendListResource::collection($list)->resource->toArray()];
    }

    /**
     * 热榜
     *
     * @param object $params
     * @return array
     */
    protected static function contentType_2(object $params): array
    {
        return [
            "hotTop" => ApiArticleListResource::collection(
                ArticleModel::query()->where("putHotTop", ArticleModel::PUT_TOP_YES)
                            ->where("status", ArticleModel::STATUS_ON)
                            ->whereIn("publishType",
                                [
                                    ArticleModel::PUBLISH_TYPE_TIMING,
                                    ArticleModel::PUBLISH_TYPE_NOW
                                ])
                            ->where("effectiveTime", "<=", time())->limit(1)->get()
            )->getIterator()->current(),
            "list"   => ApiArticleListResource::collection(ArticleModel::query()
                                                                       ->where("putHotTop", ArticleModel::PUT_TOP_NO)
                                                                       ->where("status", ArticleModel::STATUS_ON)
                                                                       ->whereIn("publishType",
                                                                           [
                                                                               ArticleModel::PUBLISH_TYPE_TIMING,
                                                                               ArticleModel::PUBLISH_TYPE_NOW
                                                                           ])
                                                                       ->where("effectiveTime", "<=", time())
                                                                       ->where("effectiveTime", ">=",
                                                                           Carbon::now()->subDays(14)->timestamp)
                                                                       ->orderByDesc("readNum")
                                                                       ->limit(20)
                                                                       ->get())->resource->toArray()
        ];
    }

    /**
     * 专题tab数据
     *
     * @param object $params
     * @return array
     */
    protected static function contentType_3(object $params): array
    {
        $pagination = ArticleCategoryModel::query()
                                          ->whereHas("articleCategoryMappingsRel", function ($query) {
                                              $query->whereHas("articleRel", function ($query) {
                                                  $query->where("status", ArticleModel::STATUS_ON)
                                                        ->whereIn("publishType",
                                                            [
                                                                ArticleModel::PUBLISH_TYPE_TIMING,
                                                                ArticleModel::PUBLISH_TYPE_NOW
                                                            ])
                                                        ->where("effectiveTime", "<=", time());
                                              });
                                          })
                                          ->where("putTop", ArticleCategoryModel::PUT_TOP_NO)
                                          ->orderBy("sort", "asc")
                                          ->orderBy("id", "desc")
                                          ->paginate(
                                              $params->pageSize,
                                              ["id", "type", "name"],
                                              'pageNum',
                                              $params->pageNum
                                          );

        return [
            "list"     => CategortyListResource::collection(
                $pagination->items()
            )->resource->toArray(),
            "total"    => $pagination->total(),
            "pageSize" => $params->pageSize,
            "pageNum"  => $params->pageNum,
        ];
    }
}
